#include "OP_SelectGeometries.h"

using namespace std;
using namespace CICore;
using namespace CIGeom;
using namespace CIView;

///<************************************************************************************************************>
///<************************************* region CONSTANTS DEFINITION ******************************************>
///<************************************************************************************************************>

/***************************************************************************************************************
************************************** endregion CONSTANTS DEFINITION ******************************************
****************************************************************************************************************/












/// <summary> 
/// Constructor 
/// </summary>
/// <param name="v"> A reference to the vector that contains the four 3D views pointers </param>
CIOps::OP_SelectGeometries::OP_SelectGeometries (vector<CIView::View*>& v)
: Operation (v), hadVerticesSelected (false) {

    newSelectionMode = Geometry::FACES_SELECTION;
}

/// <summary> 
/// Destructor 
/// </summary>
CIOps::OP_SelectGeometries::~OP_SelectGeometries() {}




///<************************************************************************************************************>
///<**************************************** region Utility Methods ********************************************>
///<************************************************************************************************************>

/// <summary> 
/// Method called to execute directly the operation 
/// </summary>
/// <returns> The operation status </returns>
int CIOps::OP_SelectGeometries::Exec() {
    switch (status) {
        case INITIAL:
            status = WAITING_FOR_EVENTS;
            break;
    }
    return status;        
}

/// <summary> 
/// Method called to undo the operation 
/// </summary>
void CIOps::OP_SelectGeometries::Undo() {
    status = UNDO;

    RestoreOldSelection();      //Restore old selection status
    UpdateViews();              //Updates the 3D views
}

/// <summary> 
/// Method called to redo the operation 
/// </summary>
void CIOps::OP_SelectGeometries::Redo() {
    status = COMPLETED;

    RestoreNewSelection();      //Restore the new selectio status
    UpdateViews();              //Updates the 3D views
}

/// <summary> 
/// Mouse Pressed event handler, called whenever the operation 
/// is in execution and a 3D view intercepts a mouse press event
/// </summary>
/// <param name="view"> The view that has thrown the event </param>
/// <param name="e"> Mouse Pressed event </param>
void CIOps::OP_SelectGeometries::MousePressEvent (CIView::View* view, QMouseEvent* e) {
    //Saving mouse click coordinates
    click.x = e->x();
    click.y = e->y();

    float x = click.x;
    float y = click.y;

    view->WindowToNormalizedCoordinates (&x, &y);                       //Normalizes the mouse cursor coordinates

    view->SetFeedbackMode (CIView::View::FEEDBACK_SELECTION);                   //Sets the view feedback mode as SELECTION

    //Computing the selection rectangle sizes for visual feedback
    FeedbackSelection& feedback = view->GetFeedbackSelection();         //A reference to the selection feedback object
    feedback.x1 = x;
    feedback.y1 = y;
    feedback.x2 = x;
    feedback.y2 = y;

    //Saving old selection and getting a boolean to indicate if there was at least one vertex selected
    hadVerticesSelected = SaveOldSelection();      

    if (!(e->modifiers()&Qt::ControlModifier))          //If is not pressed the control modifier
        scene.DeselectAllFaces();                       //deselects all faces       //TODO -> Deselect All (included geometries and groups)


    UpdateViews();                      //Updates the 3D views
}

/// <summary> 
/// Mouse Released event handler, called whenever the operation 
/// is in execution and a 3D view intercepts a mouse release event
/// </summary>
/// <param name="view"> The view that has thrown the event </param>
/// <param name="e"> Mouse Released event </param>
void CIOps::OP_SelectGeometries::MouseReleaseEvent (CIView::View* view, QMouseEvent* e) {
    double width = abs (click.x - e->x());              //The selection rectangle width (In window coordinates)
    double height = abs (click.y - e->y());             //The selection rectangle height (In window coordinates)
    double x = double (click.x + e->x()) / 2.0;         //The x-axis coordinate of the selection rectangle centre (In window coordinates)
    double y = double (click.y + e->y()) / 2.0;         //The y-axis coordinate of the selection rectangle centre (In window coordinates)
    
    if (width == 0)                                     //Width must be bigger than 0
        width = 1.0;                    
        
    if (height == 0)                                    //Height must be bigger than 0
        height = 1.0;

    scene.SetSelectionMode (newSelectionMode);          //Sets the current selection mode in the scene as faces selection
    
    if (OperationManager::IgnoreBackfaces) {            //If must ignore the backfaces
        view->makeCurrent();
        glEnable (GL_CULL_FACE);                        //enables the face culling
    }
    
    if (view->SelectGeometriesInVolume (x, y, width, height)    //Makes selection and if at least one geometry has been selected
        || hadVerticesSelected ) {                              //or the scene had at least a vertex selected before the new selection
            status = COMPLETED;                                 //sets the operation status to COMPLETED
            SaveNewSelection();                                 //saves the new selection status
    }
    else
        status = ZOMBIE;
    
    if (OperationManager::IgnoreBackfaces)              //If had to ignore the backfaces
        glDisable (GL_CULL_FACE);                       //disables the face culling

    view->SetFeedbackMode (CIView::View::FEEDBACK_NONE);                //Sets the view feedback mode as NONE

    UpdateViews();                                      //Updates the 3D views
}

/// <summary> 
/// Mouse Moved event handler, called whenever the operation 
/// is in execution and a 3D view intercepts a mouse move event
/// </summary>
/// <param name="view"> The view that has thrown the event </param>
/// <param name="e"> Mouse Moved event </param>
void CIOps::OP_SelectGeometries::MouseMoveEvent (CIView::View* view, QMouseEvent* e) {
    float x = e->x();
    float y = e->y();

    view->WindowToNormalizedCoordinates (&x, &y);                       //Normalizes the mouse cursor coordinates 

    //Computing the selection rectangle sizes for visual feedback
    FeedbackSelection& feedback = view->GetFeedbackSelection();         //A reference to the selection feedback object
    feedback.x2 = x;
    feedback.y2 = y;

    UpdateViews();                      //Updates the 3D views
}

/// <summary> 
/// Wheel event handler, called whenever the operation 
/// is in execution and a 3D view intercepts a mouse wheel event
/// </summary>
/// <param name="view"> The view that has thrown the event </param>
/// <param name="e"> Wheel event </param>
void CIOps::OP_SelectGeometries::WheelEvent (CIView::View* view, QWheelEvent* e) {
}
/***************************************************************************************************************
***************************************** endregion Utility Methods ********************************************
****************************************************************************************************************/
